#include "StdAfx.h"
#include "LHash.h"

// readme: 131221;
// name: must be different; effect: add;
// addr: also the same; effect: find;
// overwrite: can be set by user; default: true;

LHash * ghash = NULL;

LHash::LHash()
{
	lsetClassname("lhash");

	moverwrite = false;

	for (int i=0; i < HASHSIZE; i++)
	{
		hashtab[i] = NULL;
	}
}
LHash::~LHash()
{
	delall();
}

int LHash::init()
{
	return 0;
}
void LHash::exit()
{

}

void LHash::delall()
{
	hashlist_t * np;
	hashlist_t * tp;

	for (int i = 0; i < HASHSIZE; i++)
	{
		np = hashtab[i];
		while ( np != NULL)
		{
			tp = np;
			np = np->next;
			delete tp;
		}
		hashtab[i] =NULL;
	}
}
unsigned int LHash::calhash(string str )
{
	unsigned int hashval;
	const char * s= str.c_str();

	for (hashval =0; *s != '\0'; s++)
	{
		hashval = *s + 31 * hashval;
	}
	return hashval % HASHSIZE;
}
void * LHash::find(string s )
{
	hashlist_t * np;

	for ((np=hashtab[calhash(s)]); np != NULL; np = np->next )
	{
		if( np->name == s )
			return np->addr;
	}
	return NULL;
}
void * LHash::find(int idx)
{
	hashlist_t * hl = NULL;
	if( idx < 0 || idx >= HASHSIZE )	return hl;
	hl = getHlist( idx );
	if( hl == NULL )	return hl;
	return hl->addr;
}
hashlist_t * LHash::lookupn(string s )
{
	hashlist_t * np;

	for ((np=hashtab[calhash(s)]); np != NULL; np = np->next )
	{
		if( np->name == s )
			return np;
	}
	return NULL;
}
hashlist_t * LHash::lookupa(void * addr )
{
	hashlist_t * np;
	for ( int i=0; i< HASHSIZE; i++)
	{
		np = hashtab[i];
		while( np )
		{
			if( np->addr == addr )	return np;
			else np = np->next;
		}
	}
	return NULL;
}
void LHash::delHs( hashlist_t * hs )
{
	if( hs ) 
	{
		unsigned int v = calhash( hs->name );
		hashlist_t * pre = hs->pre;
		hashlist_t * next = hs->next;

		if( pre )
		{
			pre->next = next;
		}
		else 
		{
			hashtab[v] = next;
		}
		if( next )
		{
			next->pre = pre;
		}

		delete hs;
	}
}
void LHash::del( string s )
{
	hashlist_t * hs = lookupn( s );
	delHs( hs );
}
void LHash::del( void * addr )
{
	hashlist_t * hs = lookupa( addr );
	delHs( hs );
}
hashlist_t *  LHash::create( hashlist_t * pre, hashlist_t * next, string name, void * addr )
{
	hashlist_t *np = new hashlist_t; //TRACE(_T("->LHash::create: 0x%x\n"), np);	
	CString s = name.c_str();
	//TRACE(_T("--- hs_create: 0x%x, %s\n"), np, s);
	gptAddress(np, s, sizeof(hashlist_t));
	//printf("%s\n", name);
	np->pre = pre;								// 131219;
	np->next = next;
	np->addr = addr;
	np->name = name;
	return np;
}
bool LHash::add( void * addr )
{
	unsigned int d = (unsigned int )addr;
	_itoa_s( d, mchar, 10 );
	string s( mchar );

	return add( s, addr );
}
bool LHash::add( string name, void * addr)
{
	hashlist_t *np;
	unsigned int hashval;

	hashval = calhash(name);
	np = hashtab[hashval];
	if ( np == NULL)
	{
		np = create( NULL, NULL, name, addr );
		hashtab[hashval] = np;
		return true;
	}
	else
	{
		do 
		{
			if (np->name == name)
			{
				if( isOverwrite() )
				{
					np->addr = addr;
					return true;
				}
				else
				{
					TRACE(TEXT("--- hs_add: err: same name found."));
					VERIFY(false);
					return false;
				}
			}

			if (np->next == NULL)	// add to the end of the list;
			{
				hashlist_t * hl = create( np, NULL, name, addr );
				np->next = hl;
				break;
			}
			else
				np = np->next;
		} while (np!=NULL);
	}
	return true;
}

